package com.example.studyPlatform.controller.api;

import com.example.studyPlatform.controller.api.protocol.UUIDWebSocket;
import org.springframework.stereotype.Component;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;

import static com.example.studyPlatform.config.RoutingConstant.QR_SOCKET;

@Component
@ServerEndpoint(QR_SOCKET)
public class QRCodeWebSocket implements UUIDWebSocket {
    public QRCodeWebSocket() {
        new Timer().scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                uuid2session.clear();
                session2uuid.clear();
            }
            // 二维码有效期5到10分钟
        }, 0, 300_000);
    }

    // 轮换map
    private static class RotationMap<T, R> {
        private Map<T, R> newMap = new ConcurrentHashMap<>(), oldMap = new ConcurrentHashMap<>();

        R get(T t) {
            return newMap.containsKey(t) ? newMap.get(t) : oldMap.get(t);
        }

        void put(T t, R r) {
            newMap.put(t, r);
        }

        void clear() {
            oldMap.clear();
            Map map = oldMap;
            oldMap = newMap;
            newMap = map;
        }

        void remove(T t) {
            if (newMap.containsKey(t)) {
                newMap.remove(t);
            } else
                oldMap.remove(t);
        }

    }

    final static RotationMap<String, Session> uuid2session = new RotationMap<>();
    final static RotationMap<Session, String> session2uuid = new RotationMap<>();

    @OnMessage
    @Override
    public void onMessage(String uuid, Session session) {
        uuid2session.put(uuid, session);
        session2uuid.put(session, uuid);
    }

    @Override
    public boolean callback(String uuid, String data) {
        Session session = uuid2session.get(uuid);
        if (session != null) {
            try {
                session.getBasicRemote().sendText(data);
                session.close();
            } catch (IOException e) {
                e.printStackTrace();
                return false;
            }
        }
        return true;
    }

    @OnClose
    @Override
    public void onClose(Session session) {
        String uuid = session2uuid.get(session);
        if (uuid != null) {
            uuid2session.remove(uuid);
            session2uuid.remove(session);
        }
    }
}
